﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ServiceTester {
    using System.Globalization;

    using ServiceTester.ServerRentIt11;

    public partial class frmUserClient : Form {
        public UserSession uSession;
        public RentItClient rClient;

        public frmUserClient() {
            InitializeComponent();
        }

        private void frmUserClient_Load(object sender, EventArgs e) {
            rClient = new RentItClient();
            tabControl1.TabPages.Remove(tabMovie);
            tabControl1.TabPages.Remove(tabRent);
            tabControl1.TabPages.Remove(tabRating);
            cmbLengthMod.SelectedIndex = 2;
            cmbYearMod.SelectedIndex = 2;
            mnuAdmin.Visible = false;
        }

        private void btnLoginTestLogin_Click(object sender, EventArgs e) {
            btnLoginTestLogin.Enabled = false;

            if (btnLoginTestLogin.Text == "Login") {

                uSession = rClient.Login(txtLoginTestUsername.Text, txtLoginTestPassword.Text);
                if (uSession != null) {
                    lstTestLogin.Items.Clear();
                    lstTestLogin.Items.Add("UserID: " + uSession.UserId);
                    lstTestLogin.Items.Add("Name: " + uSession.Name);
                    lstTestLogin.Items.Add("Email: " + uSession.Email);
                    lstTestLogin.Items.Add("Birthday: " + uSession.Birthday);
                    lstTestLogin.Items.Add("Admin: " + uSession.IsAdmin);
                    lstTestLogin.Items.Add("Token: " + uSession.Token);
                } else {
                    lstTestLogin.Items.Clear();
                    var uInfo = rClient.GetUserInfoByEmail(txtLoginTestUsername.Text);
                    if (uInfo.Id > -1) {
                        if (rClient.IsAccountActivated(uInfo.Id)) {
                            lstTestLogin.Items.Add("Wrong password");
                        } else if(!rClient.IsAccountActivated(uInfo.Id)) {
                            lstTestLogin.Items.Add("Account must be activated first");
                            lstTestLogin.Items.Add("User ID: " + uInfo.Id);
                        }else {
                            lstTestLogin.Items.Add("Something went wrong, try again!");
                        }
                    } else {
                        lstTestLogin.Items.Add("Invalid email specified");
                    }
                }
            } else {
                rClient.Logout(uSession);
                lstTestLogin.Items.Clear();
                lstTestLogin.Items.Add("Logged out");
                uSession = null;
                lwRatings.Items.Clear();
            }

            btnLoginTestLogin.Enabled = true;
            btnLoginTestLogin.Text = (uSession == null ? "Login" : "Logout");

            var tabs = new[] { tabMovie, tabRent, tabRating };
            if(uSession != null && uSession.UserId > 0) {
                foreach (var tab in tabs.Where(tab => !this.tabControl1.TabPages.Contains(tab))) {
                    this.tabControl1.TabPages.Add(tab);
                }
                if (lwListAllMovies.Items.Count < 1) {
                    this.btnListAllMoviesRefresh_Click(sender, e);
                }
                
                if(cmbPG.Items.Count < 1) {
                    foreach(var pg in Enum.GetValues(typeof(ParentalGuidance))) {
                        cmbPG.Items.Add(pg);
                    }
                    if(cmbPG.Items.Count > 0) cmbPG.SelectedIndex = 0;
                }

                if(cmbLang.Items.Count < 1) {
                    cmbLang.Items.Add("");
                    foreach(var lang in rClient.ListMovieLanguages()) {
                        cmbLang.Items.Add(lang);
                    }
                    cmbLang.SelectedIndex = 0;
                }
            }else {
                foreach (var tab in tabs.Where(tab => this.tabControl1.TabPages.Contains(tab))) {
                    this.tabControl1.TabPages.Remove(tab);
                }
                tabControl1.SelectedTab = tabUser;
            }
            mnuAdmin.Visible = uSession != null && uSession.IsAdmin;

            if(mnuAdmin.Tag != null && mnuAdmin.Tag is frmAdmin && !((frmAdmin)mnuAdmin.Tag).IsDisposed) {
                if (mnuAdmin.Visible) {
                    ((frmAdmin)mnuAdmin.Tag).uSession = uSession;
                }else {
                    ((frmAdmin)mnuAdmin.Tag).Close();
                }
            }

            if (mnuAccount.Tag != null && mnuAccount.Tag is frmManageAccount && !((frmManageAccount)mnuAccount.Tag).IsDisposed) {
                ((frmManageAccount)mnuAccount.Tag).uSession = uSession;
            }
        }

        private void mnuExit_Click(object sender, EventArgs e) {
            this.Close();
        }

        private void mnuAccount_Click(object sender, EventArgs e) {
            if(mnuAccount.Tag == null || !(mnuAccount.Tag is frmManageAccount) || ((frmManageAccount)mnuAccount.Tag).IsDisposed) {
                mnuAccount.Tag = new frmManageAccount(this);
            }
            var f = (frmManageAccount)mnuAccount.Tag;
            f.Show();
            f.BringToFront();
        }

        private void mnuAdmin_Click(object sender, EventArgs e) {
            if (mnuAdmin.Tag == null || !(mnuAdmin.Tag is frmAdmin) || ((frmAdmin)mnuAdmin.Tag).IsDisposed) {
                mnuAdmin.Tag = new frmAdmin(this);
            }
            var f = (frmAdmin)mnuAdmin.Tag;
            f.Show();
            f.BringToFront();
        }

        private void frmUserClient_FormClosing(object sender, FormClosingEventArgs e) {
            try {
                if (rClient != null) rClient.Close();
            } catch { }
        }

        private void btnListAllMoviesRefresh_Click(object sender, EventArgs e) {
            btnListAllMoviesRefresh.Enabled = false;

            var res = rClient.ListMovies();

            lwListAllMovies.BeginUpdate();
            lwListAllMovies.Items.Clear();

            if (res != null) {
                foreach (var media in res) {
                    var lvw = new ListViewItem();
                    lvw.Tag = media;
                    lvw.Text = media.Title;
                    lvw.SubItems.Add("" + media.Year);
                    lvw.SubItems.Add(media.LengthFormatted);
                    lvw.SubItems.Add(media.Language);
                    lvw.SubItems.Add(media.ParentalGuidance.ToString());
                    lvw.SubItems.Add("" + (media.HighDefinition == XBool.True));
                    lvw.SubItems.Add(
                        media.ReleaseDate.HasValue ? media.ReleaseDate.Value.ToShortDateString() : "Unreleased");
                    lwListAllMovies.Items.Add(lvw);
                }
            }
            lwListAllMovies.EndUpdate();

            btnListAllMoviesRefresh.Enabled = true;
        }

        private void btnListAllMoviesShowInfo_Click(object sender, EventArgs e) {
            btnListAllMoviesShowInfo.Enabled = false;

            if (lwListAllMovies.SelectedItems.Count > 0) {
                for (var i = 0; i < lwListAllMovies.SelectedItems.Count; i++) {
                    var lvw = lwListAllMovies.SelectedItems[i];
                    var mid = ((MovieEntry)lvw.Tag).Id;
                    var f = new frmUserMovieInfo(this, mid);
                    f.Show();
                }
            }

            btnListAllMoviesShowInfo.Enabled = true;
        }

        private void lwListAllMovies_DoubleClick(object sender, EventArgs e) {
            btnListAllMoviesShowInfo.PerformClick();
        }

        private void btnSearch_Click(object sender, EventArgs e) {
            btnSearch.Enabled = false;

            var ms = new MovieSearchEntry {
                UserID = uSession != null ? uSession.UserId : 0,
                TitleIsPartial = true,
                AllMustMatch = this.chkSearchAllMustMatch.Checked,
                MovieEntry =
                    new MovieEntry {
                        Title = this.txtSearchMovieTitle.Text,
                        Length = (int)this.numSearchMovieLength.Value,
                        Year = (int)this.numSearchMovieYear.Value,
                        Language = cmbLang.Text,
                        ParentalGuidance = rClient.GetParentalGuidance(cmbPG.Text),
                        HighDefinition =
                            rdbQualityBoth.Checked ? XBool.Ignore : rdbQualityHD.Checked ? XBool.True : XBool.False,
                        ImdbId = txtSearchImdbId.Text
                    }
            };

            DateTime rday;
            if(DateTime.TryParse(txtSearchMovieRelease.Text, out rday)) {
                ms.ReleaseDateSpecification = DateSpecification.Complete;
                ms.MovieEntry.ReleaseDate = rday;
            } else if (DateTime.TryParseExact(txtSearchMovieRelease.Text.Substring(0, 7), "yyyy-MM", CultureInfo.InvariantCulture, DateTimeStyles.None, out rday)) {
                ms.ReleaseDateSpecification = DateSpecification.YearMonth;
                ms.MovieEntry.ReleaseDate = rday;
            } else if (DateTime.TryParseExact(txtSearchMovieRelease.Text.Substring(0,4), "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out rday)) {
                ms.ReleaseDateSpecification = DateSpecification.Year;
                ms.MovieEntry.ReleaseDate = rday;
            }

            ms.LengthDifferenceDirection = cmbLengthMod.Text == "±"
                                               ? DifferenceDirection.Both
                                               : cmbLengthMod.Text == "+"
                                                     ? DifferenceDirection.Higher
                                                     : DifferenceDirection.Lower;
            ms.YearDifferenceDirection = cmbYearMod.Text == "±"
                                               ? DifferenceDirection.Both
                                               : cmbYearMod.Text == "+"
                                                     ? DifferenceDirection.Higher
                                                     : DifferenceDirection.Lower;
            ms.LengthDifference = (int)numLengthMod.Value;
            ms.YearDifference = (int)numYearMod.Value;

            this.DoSearch(ms);

            btnSearch.Enabled = true;
        }

        private void DoSearch(MovieSearchEntry ms) {
            var res = rClient.SearchMovies(ms);
            lwListAllMovies.BeginUpdate();
            lwListAllMovies.Items.Clear();

            if (res != null) {
                foreach (var media in res) {
                    var lvw = new ListViewItem();
                    lvw.Tag = media;
                    lvw.Text = media.Title;
                    lvw.SubItems.Add("" + media.Year);
                    lvw.SubItems.Add(media.LengthFormatted);
                    lvw.SubItems.Add(media.Language);
                    lvw.SubItems.Add(media.ParentalGuidance.ToString());
                    lvw.SubItems.Add("" + (media.HighDefinition == XBool.True));
                    lvw.SubItems.Add(
                        media.ReleaseDate.HasValue ? media.ReleaseDate.Value.ToShortDateString() : "Unreleased");
                    lwListAllMovies.Items.Add(lvw);
                }
            }
            lwListAllMovies.EndUpdate();
        }

        private void btnResetSearch_Click(object sender, EventArgs e) {
            txtSearchMovieTitle.Text = "";
            txtSearchImdbId.Text = "";
            txtSearchMovieRelease.Text = "";
            rdbQualityBoth.Checked = true;
            cmbYearMod.SelectedIndex = 2;
            cmbLengthMod.SelectedIndex = 2;
            if (cmbLang.Items.Count > 0) cmbLang.SelectedIndex = 0;
            if (cmbPG.Items.Count > 0) cmbPG.SelectedIndex = 0;
            numLengthMod.Value = 0;
            numSearchMovieLength.Value = 0;
            numSearchMovieYear.Value = 0;
            numYearMod.Value = 0;
            txtSearchMovieTitle.Focus();
            chkSearchAllMustMatch.Checked = false;
        }

        private void btnRefreshSearches_Click(object sender, EventArgs e) {
            btnRefreshSearches.Enabled = false;

            var userInfos = new Dictionary<int, string> { { uSession.UserId, "You" } };

            var res = rClient.ListAllSearches(rdbMySearch.Checked ? uSession.UserId : -1, (int)numSearches.Value);

            lwSearches.BeginUpdate();
            lwSearches.Items.Clear();
            foreach(var ms in res) {
                var lvw = new ListViewItem();
                lvw.Tag = ms;

                var me = ms.MovieEntry;

                var t = me.Title.Length > 0 ? "Title: " + ms.MovieEntry.Title + "; " : "";
                t += me.Length > 0 ? "Length: " + me.Length + "; " : "";
                t += !string.IsNullOrEmpty(me.Language) ? "Language: " + me.Language + "; " : "";
                t += me.ParentalGuidance != ParentalGuidance.Ignore ? "PG: " + me.ParentalGuidance + "; " : "";
                t += me.Year > 0 ? "Year: " + me.Year + "; " : "";
                t += me.HighDefinition != XBool.Ignore ? "HD: " + (me.HighDefinition == XBool.True ? "Yes" : "No") + "; " : "";
                t += me.ReleaseDate.HasValue ? "Release: " + me.ReleaseDate.Value.ToString("yyyy-MM-dd") + "; " : "";
                t += !string.IsNullOrEmpty(me.ImdbId) ? "Imdb: " + me.ImdbId + "; " : "";
                t += ms.AllMustMatch ? "Match All" : "Match Any";

                lvw.Text = t;
                lvw.ToolTipText = t;

                if(!userInfos.ContainsKey(ms.UserID)) {
                    var ui = rClient.GetUserInfo(ms.UserID);
                    if(ui.Name.Length > 0) {
                        userInfos.Add(ui.Id, ui.Name);
                    } else {
                        ms.UserID = 0;
                    }
                }
                lvw.SubItems.Add(userInfos[ms.UserID]);

                lwSearches.Items.Add(lvw);
            }
            lwSearches.EndUpdate();

            btnRefreshSearches.Enabled = true;
        }

        private void lwSearches_Click(object sender, EventArgs e) {
            if (lwSearches.SelectedItems.Count > 0) {
                if (lwSearches.SelectedItems[0].Tag is MovieSearchEntry) {
                    var ms = (MovieSearchEntry)lwSearches.SelectedItems[0].Tag;
                    var me = ms.MovieEntry;
                    txtSearchMovieTitle.Text = me.Title;
                    numSearchMovieLength.Value = me.Length;
                    numSearchMovieYear.Value = me.Year;
                    cmbPG.Text = "" + me.ParentalGuidance;
                    cmbLang.Text = me.Language;
                    cmbLengthMod.SelectedIndex = ms.LengthDifferenceDirection == DifferenceDirection.Both
                                                     ? 2
                                                     : ms.LengthDifferenceDirection == DifferenceDirection.Lower ? 1 : 0;
                    cmbYearMod.SelectedIndex = ms.YearDifferenceDirection == DifferenceDirection.Both
                                                     ? 2
                                                     : ms.YearDifferenceDirection == DifferenceDirection.Lower ? 1 : 0;
                    numLengthMod.Value = ms.LengthDifference;
                    numYearMod.Value = ms.YearDifference;

                    rdbQualityBoth.Checked = true;
                    if (me.HighDefinition == XBool.True) {
                        rdbQualityHD.Checked = true;
                    } else if (me.HighDefinition == XBool.False) {
                        rdbQualitySD.Checked = true;
                    }

                    chkSearchAllMustMatch.Checked = ms.AllMustMatch;

                    txtSearchMovieRelease.Text = me.ReleaseDate.HasValue
                                                     ? me.ReleaseDate.Value.ToString("yyyy-MM-dd")
                                                     : "";
                    txtSearchImdbId.Text = me.ImdbId;
                }
            }
        }

        private void btnRatingRefresh_Click(object sender, EventArgs e) {
            btnRatingRefresh.Enabled = false;

            var res = rClient.ListUserRatings(uSession.UserId);

            lwRatings.BeginUpdate();
            lwRatings.Items.Clear();
            foreach(var rating in res) {
                var lvw = new ListViewItem();
                lvw.Tag = rating;

                var score = Program.GetRatingScore(rating.Rating);
                if (score > -1) {
                    var mi = rClient.MovieInfo(rating.MovieId);
                    lvw.Text = mi.Title;

                    lvw.SubItems.Add("" + score);
                    if (rating.Comment.Length > 0) {
                        lvw.Font = new Font(lvw.Font, FontStyle.Bold);
                    }
                    lwRatings.Items.Insert(0, lvw);
                }
            }
            lwRatings.EndUpdate();

            btnRatingRefresh.Enabled = true;
        }

        private void lwRatings_Click(object sender, EventArgs e) {
            if (lwRatings.SelectedItems.Count > 0) {
                var lvw = lwRatings.SelectedItems[0];
                if (lvw.Tag is RatingEntry) {
                    var re = (RatingEntry)lvw.Tag;
                    txtUserRating.Text = re.Comment;
                    return;
                }
            }
            txtUserRating.Text = "";
        }

        private void lwRatings_DoubleClick(object sender, EventArgs e) {
            if (lwRatings.SelectedItems.Count > 0) {
                var lvw = lwRatings.SelectedItems[0];
                if (lvw.Tag is RatingEntry) {
                    var re = (RatingEntry)lvw.Tag;
                    var f = new frmUserMovieInfo(this, re.MovieId);
                    f.Show();
                }
            }
        }

        private void lwAllRatings_Click(object sender, EventArgs e) {
            if (lwAllRatings.SelectedItems.Count > 0) {
                var lvw = lwAllRatings.SelectedItems[0];
                if (lvw.Tag is RatingEntry) {
                    var re = (RatingEntry)lvw.Tag;
                    txtAllRating.Text = re.Comment;
                    return;
                }
            }
            txtAllRating.Text = "";
        }

        private void lwAllRatings_DoubleClick(object sender, EventArgs e) {
            if (lwAllRatings.SelectedItems.Count > 0) {
                var lvw = lwAllRatings.SelectedItems[0];
                if (lvw.Tag is RatingEntry) {
                    var re = (RatingEntry)lvw.Tag;
                    var f = new frmUserMovieInfo(this, re.MovieId);
                    f.Show();
                }
            }
        }

        private void btnRatingAllRefresh_Click(object sender, EventArgs e) {
            btnRatingAllRefresh.Enabled = false;

            var users = new Dictionary<int, string>();
            var movies = new Dictionary<int, string>();

            var res = rClient.ListRatings();

            lwAllRatings.BeginUpdate();
            lwAllRatings.Items.Clear();
            foreach (var rating in res) {
                var lvw = new ListViewItem();
                lvw.Tag = rating;

                var score = Program.GetRatingScore(rating.Rating);
                if (score > -1) {
                    if (!movies.ContainsKey(rating.MovieId)) {
                        var mi = rClient.MovieInfo(rating.MovieId);
                        movies.Add(rating.MovieId, mi.Title);
                    }
                    if (!users.ContainsKey(rating.UserId)) {
                        var ui = rClient.GetUserInfo(rating.UserId);
                        users.Add(rating.UserId, ui.Name);
                    }

                    lvw.Text = users[rating.UserId];
                    lvw.SubItems.Add(movies[rating.MovieId]);


                    lvw.SubItems.Add("" + score);
                    if (rating.Comment.Length > 0) {
                        lvw.Font = new Font(lvw.Font, FontStyle.Bold);
                    }
                    lwAllRatings.Items.Insert(0, lvw);
                    Application.DoEvents();
                }
            }
            lwAllRatings.EndUpdate();

            btnRatingAllRefresh.Enabled = true;
        }

        private void btnRatingDelete_Click(object sender, EventArgs e) {
            btnRatingDelete.Enabled = false;

            foreach(ListViewItem lvw in lwRatings.SelectedItems) {
                if (lvw.Tag is RatingEntry) {
                    var re = (RatingEntry)lvw.Tag;
                    var res = rClient.DeleteRating(uSession, re.MovieId);
                }
            }

            btnRatingRefresh.PerformClick();

            btnRatingDelete.Enabled = true;
        }

        private void lwRents_Click(object sender, EventArgs e) {
            btnDownloadMovie.Enabled = false;
            btnDownloadMovie.Tag = null;
            if (lwRents.SelectedItems.Count > 0) {
                var lvw = lwRents.SelectedItems[0];
                if (lvw.Tag is RentSession) {
                    var rs = (RentSession)lvw.Tag;
                    btnDownloadMovie.Enabled = rs.SessionEnd >= DateTime.Now;
                    if(btnDownloadMovie.Enabled) {
                        btnDownloadMovie.Tag = rs;
                    }
                }
            }
        }

        private void btnRefreshRents_Click(object sender, EventArgs e) {
            btnRefreshRents.Enabled = false;
            btnDownloadMovie.Tag = null;
            btnDownloadMovie.Enabled = false;

            var res = rClient.UserRentSessions(uSession, chkOnlyActive.Checked);
            lwRents.BeginUpdate();
            lwRents.Items.Clear();

            foreach(var rent in res) {
                var lvw = new ListViewItem();
                lvw.Tag = rent;

                lvw.Text = rent.Movie.Title;
                lvw.SubItems.Add(rent.HD ? "Yes" : "No");
                lvw.SubItems.Add("$" + rent.Price);
                lvw.SubItems.Add(rent.SessionStart.ToLongDateString() + " " + rent.SessionStart.ToLongTimeString());
                lvw.SubItems.Add(rent.SessionEnd.ToLongDateString() + " " + rent.SessionEnd.ToLongTimeString());

                lwRents.Items.Add(lvw);
            }

            lwRents.EndUpdate();

            btnRefreshRents.Enabled = true;
        }

        private void btnDownloadMovie_Click(object sender, EventArgs e) {
            if(btnDownloadMovie.Tag != null && btnDownloadMovie.Tag is RentSession) {
                var re = (RentSession)btnDownloadMovie.Tag;
                System.Diagnostics.Process.Start(re.HD ? re.Movie.MovieDownloadUrlHD : re.Movie.MovieDownloadUrl);
            }
        }
    }
}
